﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

/// <summary>
/// 用于用户界面呈现的课表数据。
/// 该命名空间的类针对WPF的UI实现了特殊的接口，以正确地和用户交互。
/// </summary>
namespace HFUTCourseSimulation.Kernel.Data.Ui {

    public class Semester : INotifyPropertyChanged {
        public Semester(Storage.Semester rhs) {
            _startDate = rhs.StartDate;
            _weekCount = rhs.WeekCount;
            _indexCount = rhs.IndexCount;
            _breakfastAt = rhs.BreakfastAt;
            _lunchAt = rhs.LunchAt;
            _dinnerAt = rhs.DinnerAt;
            _courses = new ObservableCollection<Course>(rhs.Courses.Select((item) => new Course(item)));
        }
        public Storage.Semester ToStorage() {
            return new Storage.Semester() {
                StartDate = _startDate,
                WeekCount = _weekCount,
                IndexCount = _indexCount,
                BreakfastAt = _breakfastAt,
                LunchAt = _lunchAt,
                DinnerAt = _dinnerAt,
                Courses = _courses.Select((item) => item.ToStorage()).ToList()
            };
        }

        private DateTime _startDate;
        private string _weekCount;
        private string _indexCount;
        private string _breakfastAt;
        private string _lunchAt;
        private string _dinnerAt;
        private ObservableCollection<Course> _courses;

        public DateTime StartDate {
            get { return _startDate; }
            set { _startDate = value; OnPropertyChanged(nameof(StartDate)); }
        }
        public string WeekCount {
            get { return _weekCount; }
            set { _weekCount = value; OnPropertyChanged(nameof(WeekCount)); }
        }
        public string IndexCount {
            get { return _indexCount; }
            set { _indexCount = value; OnPropertyChanged(nameof(IndexCount)); }
        }
        public string BreakfastAt {
            get { return _breakfastAt; }
            set { _breakfastAt = value; OnPropertyChanged(nameof(BreakfastAt)); }
        }
        public string LunchAt {
            get { return _lunchAt; }
            set { _lunchAt = value; OnPropertyChanged(nameof(LunchAt)); }
        }
        public string DinnerAt {
            get { return _dinnerAt; }
            set { _dinnerAt = value; OnPropertyChanged(nameof(DinnerAt)); }
        }
        public ObservableCollection<Course> Courses {
            get { return _courses; }
            set { _courses = value; OnPropertyChanged(nameof(Courses)); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    public class Course : INotifyPropertyChanged {
        public Course(Storage.Course rhs) {
            _name = rhs.Name;
            _description = rhs.Description;
            _color = new ColorPair(rhs.Color);
            _schedules = new ObservableCollection<Schedule>(rhs.Schedules.Select((item) => new Schedule(item)));
            SubscribeScheduleChanges();
        }
        public Storage.Course ToStorage() {
            return new Storage.Course() {
                Name = _name,
                Description = _description,
                Color = _color.ToStorage(),
                Schedules = _schedules.Select((item) => item.ToStorage()).ToList()
            };
        }

        private string _name;
        private string _description;
        private ColorPair _color;
        private ObservableCollection<Schedule> _schedules;

        public string Name {
            get { return _name; }
            set { _name = value; OnPropertyChanged(nameof(Name)); }
        }
        public string Description {
            get { return _description; }
            set { _description = value; OnPropertyChanged(nameof(Description)); }
        }
        public ColorPair Color {
            get { return _color; }
            set { _color = value; OnPropertyChanged(nameof(Color)); }
        }
        public ObservableCollection<Schedule> Schedules {
            get { return _schedules; }
            set { 
                // Common codes
                _schedules = value; 
                OnPropertyChanged(nameof(Schedule));
                // We also need register a event for the change of this list,
                // because showcase schedules need it.
                SubscribeScheduleChanges();
            }
        }

        public string ShowcaseSchedules => $"共计{_schedules.Count}个课程安排";
        /// <summary>
        /// 用于订阅Schedules集合改变的通知，用于通知ShowcaseSchedules的改变。
        /// </summary>
        protected void SubscribeScheduleChanges() {
            _schedules.CollectionChanged += (sender, e) => {
                OnPropertyChanged(nameof(ShowcaseSchedules));
            };
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    public class Schedule : INotifyPropertyChanged {
        public Schedule(Storage.Schedule rhs) {
            _week = rhs.Week;
            _day = rhs.Day;
            _index = rhs.Index;
        }
        public Storage.Schedule ToStorage() {
            return new Storage.Schedule() {
                Week = _week,
                Day = _day,
                Index = _index
            };
        }

        private string _week;
        private string _day;
        private string _index;

        public string Week {
            get { return _week; }
            set { _week = value; OnPropertyChanged(nameof(Week)); }
        }
        public string Day {
            get { return _day; }
            set { _day = value; OnPropertyChanged(nameof(Day)); }
        }
        public string Index {
            get { return _index; }
            set { _index = value; OnPropertyChanged(nameof(Index)); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    public class ColorPair : INotifyPropertyChanged {
        public ColorPair(Storage.ColorPair rhs) {
            _foreground = rhs.Foreground;
            _background = rhs.Background;
        }
        public Storage.ColorPair ToStorage() {
            return new Storage.ColorPair() {
                Foreground = _foreground,
                Background = _background
            };
        }

        private Color _foreground;
        private Color _background;

        public Color Foreground {
            get { return _foreground; }
            set { _foreground = value; OnPropertyChanged(nameof(Foreground)); }
        }
        public Color Background {
            get { return _background; }
            set { _background = value; OnPropertyChanged(nameof(Background)); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

}
